package utils

import "fmt"

type Tree struct {
	icon        []string
	nbsp        string
	pidname     string
	childrenKey string

	data []map[string]interface{}
}

func NewTree() *Tree {
	t := &Tree{}
	t.icon = []string{"|", "├", "└"}
	t.nbsp = "&nbsp;"
	t.pidname = "pid"
	t.childrenKey = "childlist"
	return t
}

func (t *Tree) Init(data []map[string]interface{}, args ...interface{}) *Tree {
	t.data = data
	switch len(args) {
	case 1:
		t.pidname = args[0].(string)
	case 2:
		t.pidname = args[0].(string)
		t.nbsp = args[1].(string)
	}
	return t
}

// 得到子级数组
func (t *Tree) GetChild(myid interface{}) []map[string]interface{} {
	newData := []map[string]interface{}{}
	for _, value := range t.data {
		if _, ok := value["id"]; !ok {
			continue
		}

		if value[t.pidname] == myid {
			newData = append(newData, value)
		}
	}
	return newData
}

func (t *Tree) GetChildren(myid interface{}, withself ...interface{}) []map[string]interface{} {
	newData := []map[string]interface{}{}
	for _, value := range t.data {
		if _, ok := value["id"]; !ok {
			continue
		}

		if fmt.Sprintf("%v", value[t.pidname]) == fmt.Sprintf("%v", myid) {
			newData = append(newData, value)
			newData = append(newData, t.GetChildren(value["id"])...)
		} else if len(withself) > 0 && withself[0].(bool) && fmt.Sprintf("%v", value["id"]) == fmt.Sprintf("%v", myid) {
			newData = append(newData, value)
		}
	}
	return newData
}

func (t *Tree) GetChildrenIds(myid interface{}, withself ...interface{}) []interface{} {
	childrenList := t.GetChildren(myid, withself...)
	return ArrayColumn(childrenList, "id")
}

func (t *Tree) GetParents(myid interface{}, withself ...interface{}) []map[string]interface{} {
	pid := int64(0)
	newData := []map[string]interface{}{}

	for _, value := range t.data {
		if _, ok := value["id"]; !ok {
			continue
		}

		if value["id"] == myid {
			if len(withself) > 0 && withself[0].(bool) {
				newData = append(newData, value)
			}
			pid = value[t.pidname].(int64)
			break
		}
	}

	if pid > 0 {
		newData = append(newData, t.GetParents(pid, true)...)
	}

	return newData
}

func (t *Tree) GetTreeArray(myid interface{}, args ...string) []map[string]interface{} {
	itemprefix := ""
	if len(args) > 0 {
		itemprefix = args[0]
	}
	childs := t.GetChild(myid)
	total := len(childs)
	data := make([]map[string]interface{}, total)
	n := 0
	number := 1
	for _, value := range childs {
		j := ""
		k := ""
		if number == total {
			j += t.icon[2]
			if itemprefix != "" {
				k = t.nbsp
			}
		} else {
			j += t.icon[1]
			if itemprefix != "" {
				k = t.icon[0]
			}
		}
		spacer := ""
		if itemprefix != "" {
			spacer = itemprefix + j
		}

		value["spacer"] = spacer
		data[n] = value
		data[n][t.childrenKey] = t.GetTreeArray(value["id"], itemprefix+k+t.nbsp)
		n++
		number++
	}

	return data
}

func (t *Tree) GetTreeList(data []map[string]interface{}, args ...string) []map[string]interface{} {
	field := "name"
	if len(args) > 0 {
		field = args[0]
	}
	arr := []map[string]interface{}{}
	for _, v := range data {
		childList := []map[string]interface{}{}
		if _, ok := v["childlist"]; ok {
			childList = v["childlist"].([]map[string]interface{})
		}
		delete(v, "childlist")
		v[field] = v["spacer"].(string) + " " + v[field].(string)
		v["haschild"] = 0
		if len(childList) > 0 {
			v["haschild"] = 1
		}

		if v["id"].(int64) > 0 {
			arr = append(arr, v)
		}

		if len(childList) > 0 {
			arr = append(arr, t.GetTreeList(childList, field)...)
		}
	}
	return arr
}
